﻿using System;
using System.Linq;
using Cesave.Domain.PermisosModule.Contracts.Distritos;
using Cesave.Infrastructure.CrossCutting.IoC;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Cesave.Domain.PermisosModule.Entities;

namespace Cesave.Domain.PermisosModule.Tests.ServicesTests
{
	[TestClass]
	[DeploymentItem("Cesave.Infrastructure.Data.PermisosModule.Mock.dll")]
	[DeploymentItem("Cesave.Infrastructure.Data.PermisosModule.dll")]
	public class DistritoServiceTests
	{
		[TestMethod]
		[ExpectedException(typeof(InvalidOperationException))]
		public void FindDistritosByEstado_Empty_Guid_Throws_InvalidOperationException()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			Guid estadoGuid = Guid.Empty;
			
			// Act
			var actual = service.FindDistritosByEstado(estadoGuid);
		}

		[TestMethod]
		[ExpectedException(typeof(InvalidOperationException))]
		public void FindDistritosByEstadoAndStatus_Empty_Guid_Throws_InvalidOperationException()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			Guid estadoGuid = Guid.Empty;

			// Act
			var actual = service.FindDistritosByEstadoAndStatus(estadoGuid);
		}

		[TestMethod]
		[ExpectedException(typeof(InvalidOperationException))]
		public void FindDistritoById_Empty_Guid_Throws_InvalidOperationException()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			Guid distritoGuid = Guid.Empty;

			// Act
			var actual = service.FindDistritoByGuid(distritoGuid);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void AddDistrito_Null_Distrito_Throws_ArgumentNullException()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			// Act
			service.AddDistrito(null);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void ChangeDistrito_Null_Distrito_Throws_ArgumentNullException()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			// Act
			service.ChangeDistrito(null);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void DeleteDistrito_Null_Distrito_Throws_ArgumentNullException()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			// Act
			service.DeleteDistrito(null);
		}

		[TestMethod]
		public void FindDistritosByEstado_Invoke()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			Guid estadoGuid = new Guid("B13F5C3F-AA42-4943-A8E9-49BA546EE5D1");

			// Act
			var actual = service.FindDistritosByEstado(estadoGuid);

			// Assert
			Assert.IsNotNull(actual);
			Assert.AreEqual(2, actual.Count());
			actual.ForEach(distrito =>
			{
				Assert.AreEqual(estadoGuid, distrito.EstadoGuid);
			});
		}

		[TestMethod]
		public void FindDistritosByEstadoAndStatus_Invoke()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			Guid estadoGuid = new Guid("409D515D-E426-4401-997A-013866E9F12C");
			bool status = false;

			// Act
			var actual = service.FindDistritosByEstado(estadoGuid);

			// Assert
			Assert.IsNotNull(actual);
			Assert.AreEqual(1, actual.Count());
			actual.ForEach(distrito =>
			{
				Assert.AreEqual(estadoGuid, distrito.EstadoGuid);
				Assert.AreEqual(status, distrito.Status);
			});
		}

		/// <summary>
		/// TODO: Agregar distritos
		/// </summary>
		public void FindDistritoByGuid_Invoke()
		{
			//// Arrange
			//IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			//int distritoId = 4;

			//// Act
			//var actual = service.FindDistritoByGuid(distritoId);

			//// Assert
			//Assert.IsNotNull(actual);
			//Assert.AreEqual(distritoId, actual.DistritoId);
			//Assert.IsFalse(actual.Status);
			//Assert.AreEqual("999", actual.Numero);
		}

		[TestMethod]
		public void AddDistrito_Invoke()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			Guid distritoGuid = Guid.NewGuid();
			int distritoId = 99;
			int estadoId = 25;
			string nombre = "Distrito de prueba";
			string numero = "999";
			bool status = false;
			var expected = new Distrito
			{
				DistritoGuid = distritoGuid,
				DistritoId = distritoId,
				EstadoId = estadoId,
				Nombre = nombre,
				Numero = numero,
				Status = status,
			};

			// Act
			service.AddDistrito(expected);

			var actual = service.FindDistritoByGuid(distritoGuid);

			// Assert
			Assert.AreSame(expected, actual);
			service.DeleteDistrito(actual);
		}

		[TestMethod]
		public void ChangeDistrito_Invoke()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			Guid distritoGuid = Guid.NewGuid();
			int distritoId = 99;
			int estadoId = 25;
			string nombre = "Distrito de prueba";
			string numero = "999";
			bool status = false;
			var expected = new Distrito
			{
				DistritoGuid = distritoGuid,
				DistritoId = distritoId,
				EstadoId = estadoId,
				Nombre = nombre,
				Numero = numero,
				Status = status,
			};
			service.AddDistrito(expected);

			expected = service.FindDistritoByGuid(distritoGuid);

			expected.Numero = "1000";

			// Act
			service.ChangeDistrito(expected);

			var actual = service.FindDistritoByGuid(distritoGuid);

			// Assert
			Assert.AreEqual(expected.Numero, actual.Numero);
			service.DeleteDistrito(actual);
		}

		[TestMethod]
		public void DeleteDistrito_Invoke()
		{
			// Arrange
			IDistritoService service = IoCFactory.Resolve<IDistritoService>();

			Guid distritoGuid = Guid.NewGuid();
			int distritoId = 99;
			int estadoId = 25;
			string nombre = "Distrito de prueba";
			string numero = "999";
			bool status = false;
			var actual = new Distrito
			{
				DistritoGuid = distritoGuid,
				DistritoId = distritoId,
				EstadoId = estadoId,
				Nombre = nombre,
				Numero = numero,
				Status = status,
			};
			service.AddDistrito(actual);

			// Act
			service.DeleteDistrito(actual);

			var expected = service.FindDistritoByGuid(distritoGuid);

			// Assert
			Assert.IsNull(expected);
		}

	}
}
